<?php

//declare(strict_types=1);

namespace App\Common\Libary\Third;

use App\Setting\Service\SettingConfigService;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Annotation\Inject;
use Itaoke\ItkTopClient;
use taobao\request\AlibabaFliggyPromoteOrdersListRequest;
use taobao\TopClient;
use function Hyperf\Collection\collect;

/**
 * 选品库：https://www.dataoke.com/
 */
class TaoBao
{
    // 淘宝工具商的信息
    protected $tbAppKey = '24978294';
    protected $tbAppSecret = '49019ad1643c4ac216c41cd27d83de67';
    protected $taobao;


    /**
     * 业务类型 $serviceType 0 saas业务 1 发单业务 2 scrm 3 数据加工
     * @var 
     */
    protected $serviceType = 0;

    /**
     * 场景ID  1-动态ID转链场景：即入参的商品ID是完整的新商品ID   2-消费者比价场景：即入参的商品ID是主站的数字ID   3-商品库导购场景：即入参的商品ID是B段新商品ID
     * @var integer
     */
    protected $biz_scene_id = 0;

    /**
     * 1-自购省，2-推广赚（代理模式专属ID，代理模式必填，非代理模式不用填写该字段）
     * @var integer
     */
    protected $promotion_type = 0;

    /**
     * pid
     */
    protected $pid ;

    protected $accessToken;

    protected $sysConf;

    /**
     * 商品必须最新 淘宝
     * @var string
     */
    protected $itemMustUpToDate = false;

    /**
     * 淘宝搜索是否放弃数字ID
     * @var string
     */
    protected $giveUpNumberId = false;

    protected $itemUrl = [];
    protected $quanUrl = [];
    protected $pubUrl  = [];

    public $data;

    protected $relation_id;

    protected $content;

    public string $pic_url = '';

    #[Inject]
    protected SettingConfigService $configService;

    public function __construct()
    {
        vendor('taobao.TopClient');
        $taobao = new TopClient();
        $taobao->appkey = $this->tbAppKey;
        $taobao->secretKey = $this->tbAppSecret;
        $this->taobao = $taobao;

        $config = $this->configService->getConfigByGroupKey('affiliate_oauth_config');
        $this->sysConf = collect($config)->pluck('value', 'key')->toArray();
    }

    /**
     * 获取工具商信息
     * @param number $serviceType 业务类型 0 saas业务 1 发单业务 2 scrm 3 数据加工
     * @return TopClient
     */
    public function _get_tb_tool_top($serviceType= 0 ){

        $tb_top = new TopClient();
        if($serviceType == 1){  //发单
            $tb_top->appkey = $this->sysConf['fadan_app_key'];
            $tb_top->secretKey = $this->sysConf['fadan_app_secret'];
        }elseif($serviceType == 2){  //scrm
            $tb_top->appkey = $this->sysConf['scrm_app_key'];
            $tb_top->secretKey = $this->sysConf['scrm_app_secret'];
        }elseif($serviceType == 3){  //数据加工
            $tb_top->appkey = $this->sysConf['item_app_key'];
            $tb_top->secretKey = $this->sysConf['item_app_secret'];
        }else{
            $tb_top->appkey = $this->sysConf['saas_app_key'] ? $this->sysConf['saas_app_key'] : $this->tbAppKey;
            $tb_top->secretKey = $this->sysConf['saas_app_secret'] ? $this->sysConf['saas_app_secret'] : $this->tbAppSecret;
        }
        return $tb_top;
    }

    /**
     * 淘宝商品搜索(服务商搜索接口)
     * @param string $q
     * @param string $adzoneId
     * @param string $material_id
     * @param number $p
     * @param number $pageSize
     * @param string $sort
     * @param array $extra
     * @return array
     */
    public function search($q = '',$pid='',$session ='',$p = 1,$pageSize =20 , $material_id = '',$sort='' , $extra = []){
        $pidArr = explode("_", $pid ? $pid : $this->pid);
        vendor('taobao.request.TbkScMaterialOptionalUpgradeRequest');

        $c = $this->_get_tb_tool_top($this->serviceType);
        $req = new \TbkScMaterialOptionalUpgradeRequest;
        $sort && $req->setSort($sort);

        $req->setAdzoneId($pidArr[3]);
        $req->setSiteId($pidArr[2]);
        $q && $req->setQ($q);
        $req->setPageNo($p);
        //额外参数保存
        foreach ($extra as $k=>$v){
            $req->putOtherTextParam($k, $v);
        }
        $this->biz_scene_id && $req->putOtherTextParam('biz_scene_id',  $this->biz_scene_id);
        $resp = $c->execute($req ,$session ? $session : $this->accessToken);
        $otheritem = objtoarr($resp);
        //    wlog($otheritem , "--搜索-----------------:");

        $map_data = isset($otheritem['result_list']['map_data']) ? $otheritem['result_list']['map_data'] : [];
        $this->data = $otheritem;
        return  $map_data;
    }

    /**
     * 获取飞猪订单
     * @param integer $startTime 开始时间
     * @param integer $endTime 结束时间
     * @param integer $nextNum 页码号
     * @return array
     */
    public function getFeuZhuOrder($startTime, $endTime, $nextNum) {
        vendor('taobao.request.AlibabaFliggyPromoteOrdersListRequest');
        $req = new AlibabaFliggyPromoteOrdersListRequest();
        $req->setPageNo($nextNum);
        $req->setBeforeModifyTime(date('Y-m-d H:i:s', $endTime));
        $req->setAfterModifyTime(date('Y-m-d H:i:s', $startTime));

        return objtoarr($this->taobao->execute($req));
    }

    public function _get_itk_top()
    {
        vendor('Itaoke.ItkTopClient');
        $top = new ItkTopClient();
        $top->appkey = '1037161345';
        $top->secretKey = '1fa6ae26-fee4-3265-b7ce-2167d2754be9';
        return $top;
    }

    /**
     * 调用搜索
     * @param  $keyword
     * @param  $session
     * @param  $pid
     * @param string $r_id
     * @param string $quanUrl
     * @param number $num
     * @return array|mixed
     */
    public function tranSearch($keyword,$session , $pid ,$r_id='',$quanUrl=''){
        $tb_top = $this->_get_itk_top();
        $req = $tb_top->load_api('ItaokeTsearchGetRequest');
        $req->setPid($pid);
        $req->putOtherTextParam('session', $session);				   // 设置采集数据分类ID
        $req->putOtherTextParam('keyword', base64_encode($keyword));				// 设置最小佣金
        $r_id && $req->putOtherTextParam('r_id', $r_id);
        $req->putOtherTextParam('twpd', 1);
        $quanUrl && $req->putOtherTextParam('quanUrl', $quanUrl);
        $this->itemMustUpToDate && $req->putOtherTextParam('itemMustUpToDate', 1);
        $this->giveUpNumberId && $req->putOtherTextParam('giveUpNumberId', 1);

        $resp = (array)$tb_top->execute($req);
        if($resp['status'] == '0000')
        {
            $res = $resp['data'];
        }else{
            $res = $resp;
        }

        unset($tb_top);
        unset($req);
        unset($resp);
        return $res;
    }


    /**
     * 设置素材必须最新
     * @param string $bool
     * @return boolean
     */
    public function setItemMustUpTodate($bool = true):TaoBao
    {
        $this->itemMustUpToDate = $bool;
        return $this;
    }

    /**
     * 放弃数字ID
     * @param string $bool
     */
    public function giveUpTbNumberId($bool = true):TaoBao
    {
        $this->giveUpNumberId = $bool;
        return $this;
    }

    /**
     * 获取优惠券
     * @param  $couponList
     * @param  $price
     * @return array|
     */
    public function getTbItemCoupon($couponList ,$price = 0){
        if(empty($couponList)){
            return [];
        }

        $sort = array_column($couponList, 'promotion_fee');
        array_multisort($sort,SORT_DESC,$couponList);
        foreach ($couponList as $k=>$v){
            if(in_array($v['promotion_title'], ['商品券','店铺券'])){
                return $v;
            }
        }
        return [];
    }


    public function pregUrl($content)
    {
        $array2 = [];
        preg_match_all('@(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))@',$content,$array2);
        $urls = $array2[0];
        return $urls;
    }

    public function pregToken($content)
    {
        $m = [];
        $tokens = '\x{ffe5}|\€|\(|\)|\￥|\《|\/|\✔|\$|\₤|\₳|\¢|\¤|\฿|\₵|\₡|\₫|\ƒ|\₲|\₭|\£|\₥|\₦|\₱|\〒|\₮|\₩|\₴|\！|\，|\₪|\៛|\﷼|\₢|\ℳ|\₰|\₯|\₠|\₣|\₧|[\x{4e00}-\x{9fa5}]|[\x{1F600}-\x{1F64F}]|[\x{1F300}-\x{1F5FF}]|[\x{1F680}-\x{1F6FF}]|[\x{2600}-\x{26FF}]|[\x{2700}-\x{27BF}]';
        //检查口令，进行口令解析（主站+联盟）
        $preg = "#({$tokens})([a-zA-Z0-9 ]{11,30})({$tokens})#isu";
        preg_match_all($preg, $content, $m);
        $twpds = $m[0];
        return $twpds;
    }

    /**
     * 根据商品ID进行搜索
     * @param $id
     * @param $pid
     * @param $accessToken
     * @return array
     */
    public function searchById($id , $pid ='',$accessToken = '')
    {
        if(is_numeric($id)){
            $url = "https://detail.tmall.com/item.htm?id={$id}";
            $this->setBizSceneId(2);
        }else{
            $url = "https://uland.taobao.com/item/edetail?id={$id}";
        }
        return $this->search($url ,$pid ,$accessToken);
    }

    /**
     * 指定场景 1-动态ID转链场景，2-消费者比价场景，3-商品库导购场景
     * @return Taobao
     */
    public function setBizSceneId($id = 0)
    {
        $this->biz_scene_id = $id;
        return $this;
    }

    /**
     * 根据文案内的链接来查找所有包括的淘宝链接
     * @param  $urls
     */
    public function findItemAndCouponFromUrls($urls){
        foreach ($urls as $k=>$v){
            $itemUrl = preg_replace('/\s/u', '',$v);
            //主站链接
            if(strpos($v,'id=')!==false && strpos($v,'uland.taobao.com')===false){
                $this->setBizSceneId(2);
                array_push($this->itemUrl, $itemUrl);
            }elseif (strpos($v,'uland.taobao.com/quan/detail')!==false){
                array_push($this->quanUrl, $itemUrl);
            }elseif (strpos($v,'s.click')!==false || strpos($v,'uland.taobao.com')!==false){
                array_push($this->pubUrl, $itemUrl);
            }
        }
    }

    public function transferChain(string $content,string $pid,string $accessToken,mixed $relationId = '',string $quanUrl = '',int $num = 1): array
    {
        $res = $this->setPid($pid)
            ->setRelationId($relationId)
            ->setAccessToken($accessToken)
            ->setContent($content)
            ->parse()
            ->convert();
        if(isset($res['data'])){
            $item = $res['data']['material_url_list']['material_url_list'][0];

            //物料类型 1—单品 2—店铺 3—会场 4-承接开放 5-优惠券
            if(!empty($item['link_info_dto'])){
                $contentInfo = $item['link_info_dto'];
                $tkl = '';
                $url = '';
                if(!empty($contentInfo['coupon_short_tpwd'])){
                    $tkl = $contentInfo['coupon_short_tpwd'];
                }elseif(!empty($contentInfo['cps_short_tpwd'])){
                    $tkl = $contentInfo['cps_short_tpwd'];
                }

                if(!empty($contentInfo['coupon_short_url'])){
                    $url = $contentInfo['coupon_short_url'];
                }elseif(!empty($contentInfo['cps_short_url'])){
                    $url = $contentInfo['cps_short_url'];
                }
                //双链接
                if(strpos($content , "https://uland.taobao.com")!==false){
                    $geturl = parse_url($content);
                    $query = $geturl['query'] ?? '';
                    if($query){
                        $params = convert_url_query($query);
                        $tbItemId = $params['id'];
                    }else{
                        $tbItemId = '';
                    }
                }else{
                    $parseRes = $this->parseContent($content);
                    $parseRes = $parseRes['data']['material_url_list']['material_url_list'][0];
                    $tbItemId = $parseRes['link_info_dto']['material_id'];
                }

                if($tbItemId){
                    //单品进行搜索商品详情
                    $searchItem = $this->setBizSceneId(0)->searchById($tbItemId ,$pid,$accessToken);
                    if(!empty($searchItem)){
                        if($searchItem[0]['item_basic_info']['white_image'] ){
                            $this->pic_url = strpos($searchItem[0]['item_basic_info']['white_image'], 'http') === false ? 'http:' . $searchItem[0]['item_basic_info']['white_image'] : $searchItem[0]['item_basic_info']['white_image'];
                        }else{
                            $this->pic_url = strpos($searchItem[0]['item_basic_info']['pict_url'], 'http') === false ? 'http:' . $searchItem[0]['item_basic_info']['pict_url'] : $searchItem[0]['item_basic_info']['pict_url'];
                        }
                    }
                }
                return [
                    'tkl' => $tkl,
                    'url' => $url,
                ];
            }
        }
        $num++;
        if($num<=3){
            Coroutine::sleep(0.2);
            return $this->transferChain($content, $pid, $accessToken ,$relationId,$quanUrl,$num);
        }

        logger()->info("淘宝转链接失败PID:{$pid},渠道{$relationId},授权{$accessToken},原内容:{$content}",$res);
        return [
            'tkl' => '',
            'url' => '',
        ];
    }

    /**
     * 万能转链接，支持把老口令转成自己的
     * @param $content
     * @return mixed
     */
    public function convert($material_list = ''){
        !$material_list && $material_list = $this->content;
        vendor("taobao.request.TbkScGeneralLinkConvertRequest");
        $c = $this->_get_tb_tool_top($this->serviceType);
        $req = new \TbkScGeneralLinkConvertRequest;
        $this->biz_scene_id && $req->putOtherTextParam('biz_scene_id' ,$this->biz_scene_id);
        $this->promotion_type && $req->setPromotionType($this->promotion_type);
        $pids = explode('_', $this->pid);
        $req->setAdzoneId($pids[3]);
        $req->setSiteId($pids[2]);
        $req->setMaterialList($material_list);
        $this->relation_id && $req->setRelationId($this->relation_id);
        $resp = $c->execute($req,$this->accessToken);
        $otheritem = objtoarr($resp);
        return $otheritem;
    }

    /**
     * 万能解析
     * @param $material_list
     * @return array
     */
    public function parseContent($material_list = ''){
        !$material_list && $material_list = $this->content;

        vendor('taobao.request.TbkScGeneralLinkParseRequest');
        vendor('taobao.domain.LkMaterialDTO');

        $c = $this->_get_tb_tool_top($this->serviceType);
        $req = new \TbkScGeneralLinkParseRequest;
        $this->biz_scene_id && $req->putOtherTextParam('biz_scene_id' ,$this->biz_scene_id);
        $pids = explode('_', $this->pid);
        $req->setAdzoneId($pids[3]);
        $this->relation_id && $req->setRelationId($this->relation_id);

        $material_dto = new \LkMaterialDTO;
        $material_dto->material_url=$material_list;
        $req->setMaterialDto(json_encode($material_dto));
        $resp = $c->execute($req,$this->accessToken);
        $otheritem = objtoarr($resp);
        return $otheritem;
    }

    public function setContent($content)
    {
        $this->content = $content;
        //匹配口令
        $tpwd = $this->pregToken($content);
        if(!empty($tpwd) && $tpwd[0]){
            $this->content = $tpwd[0];
        }
        return $this;
    }

    /**
     * @return $this
     */
    public function parse()
    {
        $urls = $this->pregUrl($this->content);
        if(!empty($urls)){
            $this->findItemAndCouponFromUrls($urls);
        }
        return $this;
    }

    public function setPid($pid)
    {
        $pid && $this->pid = $pid;
        return $this;
    }

    public function setRelationId($relation_id)
    {
        $this->relation_id = $relation_id;
        return $this;
    }

    public function setAccessToken($token)
    {
        $this->accessToken = $token;
        return $this;
    }
}